#ifndef __DESCRIPTORS_H
#define __DESCRIPTORS_H
#include "typedef.h"
#include "interrupts.h"

#define         GDT_ENTRIES             5
#define 	KERNEL_CS		0x08
#define		KERNEL_DS		0x10
#define		USER_CS		        0x18
#define		USER_DS		        0x20

#define		INTERRUPT_FLAGS		0x8E

struct idt_entry {
  word base_lo;
  word selector;
  byte zero;
  byte flags;
  word base_hi;
} __attribute__((packed));

typedef struct idt_entry IDT_entry;

struct _IDTR {
  word limit;
  dword offset;
} __attribute__((packed));

typedef struct _IDTR IDTR;

struct gdt_entry {
  u16 limit_low;   
  u16 base_low;    
  u8 base_middle; 
  u8 access;     
  u8  granularity;
  u8  base_high;  
} __attribute__((packed));

typedef struct gdt_entry GDT_entry;

struct _gdtr {
   u16 limit; 
   u32 base;
}  __attribute__((packed));

typedef struct _gdtr GDTR;

// A struct describing a Task State Segment. taken from James Molloy
struct tss_entry_struct {
   u32 prev_tss;   // The previous TSS - if we used hardware task switching this would form a linked list.
   u32 esp0;       // The stack pointer to load when we change to kernel mode.
   u32 ss0;        // The stack segment to load when we change to kernel mode.
   u32 esp1;       // Unused...
   u32 ss1;
   u32 esp2;
   u32 ss2;
   u32 cr3;
   u32 eip;
   u32 eflags;
   u32 eax;
   u32 ecx;
   u32 edx;
   u32 ebx;
   u32 esp;
   u32 ebp;
   u32 esi;
   u32 edi;
   u32 es;         // The value to load into ES when we change to kernel mode.
   u32 cs;         // The value to load into CS when we change to kernel mode.
   u32 ss;         // The value to load into SS when we change to kernel mode.
   u32 ds;         // The value to load into DS when we change to kernel mode.
   u32 fs;         // The value to load into FS when we change to kernel mode.
   u32 gs;         // The value to load into GS when we change to kernel mode.
   u32 ldt;        // Unused...
   u16 trap;
   u16 iomap_base;
} __attribute__((packed));

typedef struct tss_entry_struct tss_entry_t; 


/////////////////////////////////////////////////////////////////
// gdt functions
/////////////////////////////////////////////////////////////////
void init_GDT();
// defined in asm.s
extern void flush_GDT(u32);


/////////////////////////////////////////////////////////////////
// idt functions
/////////////////////////////////////////////////////////////////
void init_IDT();
/* install an isr into the idt */
void install_handler(int, dword);
/* defined in idt.s */
extern void load_IDT(u32);

#endif
